package com.review.cli;

import com.review.git.GitDiffService;
import com.review.model.DiffRequest;
import com.review.model.DiffResult;
import com.review.graph.CallGraphService;
import com.review.model.CallGraphBuildRequest;
import com.review.model.CallGraph;
import com.review.analysis.StaticAnalysisService;
import com.review.model.SarifModels;
import com.review.impact.ImpactAnalysisService;
import com.review.llm.LlmProvider;
import com.fasterxml.jackson.databind.ObjectMapper;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

@Command(name = "agent", description = "Run code review against local or commit diffs")
public class ReviewCommand implements Runnable {

	@Option(names = "--mode", required = true, description = "staged|working|diff|commits|branches")
	private String mode;

	@Option(names = "--base")
	private String base;

	@Option(names = "--head")
	private String head;

	@Option(names = "--path", description = "Repository path", defaultValue = ".")
	private String repoPath;

	@Override
	public void run() {
		try {
			ObjectMapper om = new ObjectMapper();
			GitDiffService diffService = new GitDiffService(repoPath);
			DiffRequest req = new DiffRequest(mode, base, head);
			DiffResult diff = diffService.computeDiff(req);

			CallGraphService cgService = new CallGraphService();
			CallGraphBuildRequest cgReq = new CallGraphBuildRequest(repoPath, "CHA");
			CallGraph graph = cgService.build(cgReq);

			ImpactAnalysisService impact = new ImpactAnalysisService();
			ImpactAnalysisService.ImpactResult imp = impact.analyze(diff, graph, 2);

			StaticAnalysisService analysis = new StaticAnalysisService();
			SarifModels.SarifRun semgrep = null;
			try { semgrep = analysis.runSemgrep(new java.io.File(repoPath)); } catch (Exception e) { /* optional */ }

			var evidence = om.createObjectNode();
			evidence.put("repoPath", repoPath);
			evidence.set("diff", om.valueToTree(diff));
			evidence.set("impact", om.valueToTree(imp));
			evidence.set("callGraph", om.valueToTree(graph));
			if (semgrep != null) evidence.set("semgrep", om.valueToTree(semgrep));

			String instruction = "You are a code review agent. Analyze the evidence JSON and output structured findings as JSON with fields: findings:[{title,severity,explanation,locations:[{file,line}] ,suggestedFix(optional diff)}], summary. Keep output strictly JSON.";
			String prompt = instruction + "\nEVIDENCE:\n" + om.writerWithDefaultPrettyPrinter().writeValueAsString(evidence);

			LlmProvider llm = new LlmProvider();
			var llmResult = llm.analyze(prompt);

			var output = om.createObjectNode();
			output.set("evidence", evidence);
			output.set("llm", llmResult);
			System.out.println(om.writerWithDefaultPrettyPrinter().writeValueAsString(output));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

